package com.web.service.impl;

import com.dto.BaseDto;
import com.dto.MessageEnum;
import com.entity.*;
import com.exception.CustomException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.page.PageInfo;
import com.web.dao.CustomerDao;
import com.web.dao.ExplaindetailrecordForCustomerDao;
import com.web.dao.MongodbDao;
import com.web.dao.RedisGeneratorDao;
import com.web.service.CustomerService;
import com.web.service.CustomerServiceForEmployrecord;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class CustomerServiceImpl implements CustomerService, CustomerServiceForEmployrecord {
    @Resource
    CustomerDao customerDao;
    @Resource
    RedisGeneratorDao redisGeneratorDao;

    @Resource
    ExplaindetailrecordForCustomerDao explaindetailrecordForCustomerDao;

    @Resource
    MongodbDao mongodbDao;

    public BaseDto<Customer> getAll() throws Exception {
        List<Customer> customers = customerDao.getAll();
        MessageEnum messageEnum = customers.size() > 0? MessageEnum.GETALLSTUDENTSUCCESS:MessageEnum.GETALLSTUDENTNODATA;
        BaseDto<Customer> dto = new BaseDto(messageEnum,customers);

        return dto;
    }




    public BaseDto<Customer> selectByPrimaryKeyWithDietian(String cid) throws Exception {
        Customer customer = customerDao.selectByPrimaryKeyWithDietian(cid);
        MessageEnum messageEnum = Optional.ofNullable(customer).isPresent()? MessageEnum.GETALLSTUDENTSUCCESS:MessageEnum.GETALLSTUDENTNODATA;
        BaseDto<Customer> dto = new BaseDto(messageEnum,customer);

        return dto;
    }

    /**
     *  按营养师姓名 搜索 某个用户的 营养师id集合  ，1.根据关联查询出  和我有关联的营养师集合，根据名字 在集合中筛选
     * @param cid
     * @param petternName
     * @return
     * @throws Exception
     */
    public BaseDto<String> searchMyDietitianIds(String cid,String petternName) throws Exception{
        Customer customer = customerDao.selectByPrimaryKeyWithDietian(cid);
        Set<String> idsSet = new HashSet<String>();
        for(Employrecord employrecord : customer.getEmployrecords()){
            Dietitian dietitian = employrecord.getDietitian();
            if(dietitian.getDname().indexOf(petternName)>=0){
                idsSet.add(dietitian.getDid());
            }
        }
        List<String> ids = idsSet.stream().collect(Collectors.toList());

        MessageEnum messageEnum = ids.size()>0? MessageEnum.GETALLSTUDENTSUCCESS:MessageEnum.GETALLSTUDENTNODATA;
        BaseDto<String> dto = new BaseDto(messageEnum,ids);

        return dto;
    }

    //表示首先到 缓存管理器  myCache 找有没有数据，根据cacheId
    @Cacheable(value = "myCache",key = "#cacheId")
    public BaseDto<Customer> getCustomersByPage(PageInfo pageInfo,String cacheId) throws Exception {
        List<Customer> customers = customerDao.getCustomersByPage(pageInfo);
        MessageEnum messageEnum = customers.size() > 0? MessageEnum.GETCUSTOMERBYPAGESUCCESS:MessageEnum.GETCUSTOMERBYPAGEFAIL;
        BaseDto<Customer> dto = new BaseDto(messageEnum,customers);

        return dto;
    }



    public BaseDto<String> searchCustomerIdsByName(String petternName) throws Exception {
        List<String> customerIds = customerDao.searchCustomerIdsByName(petternName);
        MessageEnum messageEnum = customerIds.size() > 0? MessageEnum.GETCUSTOMERBYPAGESUCCESS:MessageEnum.GETCUSTOMERBYPAGEFAIL;
        BaseDto<String> dto = new BaseDto(messageEnum,customerIds);

        return dto;
    }

    //表示首先到 缓存管理器  myCache 找有没有数据，根据cacheId
    public BaseDto<Customer> getCustomersByPage(PageInfo pageInfo) throws Exception {
        List<Customer> customers = customerDao.getCustomersByPage(pageInfo);
        MessageEnum messageEnum = customers.size() > 0? MessageEnum.GETCUSTOMERBYPAGESUCCESS:MessageEnum.GETCUSTOMERBYPAGEFAIL;
        BaseDto<Customer> dto = new BaseDto(messageEnum,customers);

        return dto;
    }

    /**
     * 添加会员
     * @param customer
     * @return
     * @throws Exception
     */
    public BaseDto<Customer> add(Customer customer) throws Exception {
        int result = customerDao.add(customer);
        MessageEnum messageEnum = result > 0? MessageEnum.ADDCUSTOMERSUCCESS:MessageEnum.ADDCUSTOMERFAIL;
        BaseDto<Customer> dto = new BaseDto(messageEnum,result);

        return dto;
    }

    /**
     * 根据主键 和 扣款金额 判断能否扣款成功
     * @param cid
     * @param subCost
     * @return
     * @throws Exception
     */
    public BaseDto<Customer> subCustomerCost(String cid,Integer subCost) throws Exception {
        //根据 会员号 查询出的余额大于扣款余额 扣款才成功
        Integer cost = customerDao.selectByPrimaryKey(cid).getCcost();
        if(cost < subCost){
            throw new CustomException("余额不足，扣款失败");
        }
        Customer customer  = new Customer();
        customer.setCid(cid);
        customer.setCcost(cost-subCost);
        int result = customerDao.update(customer);
        MessageEnum messageEnum = result > 0? MessageEnum.ADDCUSTOMERSUCCESS:MessageEnum.ADDCUSTOMERFAIL;
        BaseDto<Customer> dto = new BaseDto(messageEnum,result);

        return dto;
    }

    /**
     * 根据主键 和 充值成功
     * @param cid
     * @param addCost
     * @return
     * @throws Exception
     */
    public BaseDto<Customer> addCustomerCost(String cid,Integer addCost) throws Exception {
        //根据 会员号 查询出的余额大于扣款余额 扣款才成功
        Integer cost = customerDao.selectByPrimaryKey(cid).getCcost();

        Customer customer  = new Customer();
        customer.setCid(cid);
        customer.setCcost(cost+addCost);
        int result = customerDao.update(customer);
        MessageEnum messageEnum = result > 0? MessageEnum.ADDCUSTOMERSUCCESS:MessageEnum.ADDCUSTOMERFAIL;
        BaseDto<Customer> dto = new BaseDto(messageEnum,result);

        boolean  isBreak = false;
        for(int i=0;i<2;i++) {

            List<String> strs = redisGeneratorDao.getListValueByKey("CustomerIds"+(i+1));
           // System.out.println("CustomerIds"+(i+1)+"-----");
            if(Optional.ofNullable(strs).isPresent()) {
                for (String string : strs) {
                    if (string.equals(cid)) {//如果从redis中查询出的id缓存中有和 本次会员id相等说明本次操作需要跟新缓存
                        isBreak = true;
                        redisGeneratorDao.deleteKey("CustomerByPage" + (i + 1));
                        break;
                    }
                }
            }
            if(isBreak){
                break;
            }
        }
        return dto;
    }

    /**
     * 添加一个订餐记录 需要提供属于的营养计划编号  顾客编号 套餐编号
     * @param prid
     * @param smid
     * @param cid
     * @return
     */
    @Transactional(rollbackFor = CustomException.class)
     public BaseDto addOrder(Integer prid,String smid,String cid) throws Exception {
        //每次下单订餐 需要 添加 订餐的时间 价格 套餐编号

        String exid = UUID.randomUUID().toString().replaceAll("-", "");
        Explaindetailrecord explaindetailrecord = new Explaindetailrecord();
        explaindetailrecord.setExid(exid);//uuid产生的流水号
        explaindetailrecord.setPrid(prid);//计划编号
        explaindetailrecord.setSmid(smid);//套餐编号
        explaindetailrecord.setBuytime(new Date());//购买时间
        explaindetailrecord.setSmprice("30");//价格
        explaindetailrecord.setCid(cid);
        int addResult = explaindetailrecordForCustomerDao.add(explaindetailrecord);
        //完成点餐录入之后，需要查询整个用户新的 最新合同关联营养计划 关联点餐关联套餐关联食品的组合
        Customer customer = customerDao.selectByPrimaryKeyWithFood(cid);
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(customer);
        MongoDBDocument<Customer> mongoDBDocument = new MongoDBDocument(customer.getCid(), customer);


        //将最新的内容录入mongodb
        mongodbDao.save(mongoDBDocument,"customerWithFood");

        BaseDto dto = addResult>0?new BaseDto(MessageEnum.ADDCUSTOMERSUCCESS):new BaseDto(MessageEnum.ADDCUSTOMERFAIL);

        return dto;
     }
    public static void main(String[] args) {
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        System.out.println(uuid);
    }
}
